package com.afollestad.materialdialogs.internal;

import android.annotation.SuppressLint;
import android.content.Context;
import android.content.res.ColorStateList;
import android.graphics.PorterDuff;
import android.graphics.drawable.Drawable;
import android.os.Build;
import android.support.annotation.ColorInt;
import android.support.annotation.NonNull;
import android.support.v4.content.ContextCompat;
import android.support.v4.graphics.drawable.DrawableCompat;
import android.support.v7.widget.AppCompatEditText;
import android.util.Log;
import android.widget.CheckBox;
import android.widget.EditText;
import android.widget.ProgressBar;
import android.widget.RadioButton;
import android.widget.SeekBar;
import android.widget.TextView;
import com.afollestad.materialdialogs.R;
import com.afollestad.materialdialogs.util.DialogUtils;
import java.lang.reflect.Field;

/** Tints widgets */
@SuppressLint("PrivateResource")
public class MDTintHelper {

  public static void setTint(@NonNull RadioButton radioButton, @NonNull ColorStateList colors) {
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
      radioButton.setButtonTintList(colors);
    } else {
      Drawable radioDrawable =
          ContextCompat.getDrawable(radioButton.getContext(), R.drawable.abc_btn_radio_material);
      Drawable d = DrawableCompat.wrap(radioDrawable);
      DrawableCompat.setTintList(d, colors);
      radioButton.setButtonDrawable(d);
    }
  }

  public static void setTint(@NonNull RadioButton radioButton, @ColorInt int color) {
    final int disabledColor = DialogUtils.getDisabledColor(radioButton.getContext());
    ColorStateList sl =
        new ColorStateList(
            new int[][] {
              new int[] {android.R.attr.state_enabled, -android.R.attr.state_checked},
              new int[] {android.R.attr.state_enabled, android.R.attr.state_checked},
              new int[] {-android.R.attr.state_enabled, -android.R.attr.state_checked},
              new int[] {-android.R.attr.state_enabled, android.R.attr.state_checked}
            },
            new int[] {
              DialogUtils.resolveColor(radioButton.getContext(), R.attr.colorControlNormal),
              color,
              disabledColor,
              disabledColor
            });
    setTint(radioButton, sl);
  }

  public static void setTint(@NonNull CheckBox box, @NonNull ColorStateList colors) {
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
      box.setButtonTintList(colors);
    } else {
      Drawable checkDrawable =
          ContextCompat.getDrawable(box.getContext(), R.drawable.abc_btn_check_material);
      Drawable drawable = DrawableCompat.wrap(checkDrawable);
      DrawableCompat.setTintList(drawable, colors);
      box.setButtonDrawable(drawable);
    }
  }

  public static void setTint(@NonNull CheckBox box, @ColorInt int color) {
    final int disabledColor = DialogUtils.getDisabledColor(box.getContext());
    ColorStateList sl =
        new ColorStateList(
            new int[][] {
              new int[] {android.R.attr.state_enabled, -android.R.attr.state_checked},
              new int[] {android.R.attr.state_enabled, android.R.attr.state_checked},
              new int[] {-android.R.attr.state_enabled, -android.R.attr.state_checked},
              new int[] {-android.R.attr.state_enabled, android.R.attr.state_checked}
            },
            new int[] {
              DialogUtils.resolveColor(box.getContext(), R.attr.colorControlNormal),
              color,
              disabledColor,
              disabledColor
            });
    setTint(box, sl);
  }

  public static void setTint(@NonNull SeekBar seekBar, @ColorInt int color) {
    ColorStateList s1 = ColorStateList.valueOf(color);
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
      seekBar.setThumbTintList(s1);
      seekBar.setProgressTintList(s1);
    } else if (Build.VERSION.SDK_INT > Build.VERSION_CODES.GINGERBREAD_MR1) {
      Drawable progressDrawable = DrawableCompat.wrap(seekBar.getProgressDrawable());
      seekBar.setProgressDrawable(progressDrawable);
      DrawableCompat.setTintList(progressDrawable, s1);
      if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
        Drawable thumbDrawable = DrawableCompat.wrap(seekBar.getThumb());
        DrawableCompat.setTintList(thumbDrawable, s1);
        seekBar.setThumb(thumbDrawable);
      }
    } else {
      PorterDuff.Mode mode = PorterDuff.Mode.SRC_IN;
      if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.GINGERBREAD_MR1) {
        mode = PorterDuff.Mode.MULTIPLY;
      }
      if (seekBar.getIndeterminateDrawable() != null) {
        seekBar.getIndeterminateDrawable().setColorFilter(color, mode);
      }
      if (seekBar.getProgressDrawable() != null) {
        seekBar.getProgressDrawable().setColorFilter(color, mode);
      }
    }
  }

  public static void setTint(@NonNull ProgressBar progressBar, @ColorInt int color) {
    setTint(progressBar, color, false);
  }

  private static void setTint(
      @NonNull ProgressBar progressBar, @ColorInt int color, boolean skipIndeterminate) {
    ColorStateList sl = ColorStateList.valueOf(color);
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
      progressBar.setProgressTintList(sl);
      progressBar.setSecondaryProgressTintList(sl);
      if (!skipIndeterminate) {
        progressBar.setIndeterminateTintList(sl);
      }
    } else {
      PorterDuff.Mode mode = PorterDuff.Mode.SRC_IN;
      if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.GINGERBREAD_MR1) {
        mode = PorterDuff.Mode.MULTIPLY;
      }
      if (!skipIndeterminate && progressBar.getIndeterminateDrawable() != null) {
        progressBar.getIndeterminateDrawable().setColorFilter(color, mode);
      }
      if (progressBar.getProgressDrawable() != null) {
        progressBar.getProgressDrawable().setColorFilter(color, mode);
      }
    }
  }

  private static ColorStateList createEditTextColorStateList(
      @NonNull Context context, @ColorInt int color) {
    int[][] states = new int[3][];
    int[] colors = new int[3];
    int i = 0;
    states[i] = new int[] {-android.R.attr.state_enabled};
    colors[i] = DialogUtils.resolveColor(context, R.attr.colorControlNormal);
    i++;
    states[i] = new int[] {-android.R.attr.state_pressed, -android.R.attr.state_focused};
    colors[i] = DialogUtils.resolveColor(context, R.attr.colorControlNormal);
    i++;
    states[i] = new int[] {};
    colors[i] = color;
    return new ColorStateList(states, colors);
  }

  public static void setTint(@NonNull EditText editText, @ColorInt int color) {
    ColorStateList editTextColorStateList =
        createEditTextColorStateList(editText.getContext(), color);
    if (editText instanceof AppCompatEditText) {
      //noinspection RestrictedApi
      ((AppCompatEditText) editText).setSupportBackgroundTintList(editTextColorStateList);
    } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
      editText.setBackgroundTintList(editTextColorStateList);
    }
    setCursorTint(editText, color);
  }

  private static void setCursorTint(@NonNull EditText editText, @ColorInt int color) {
    try {
      Field fCursorDrawableRes = TextView.class.getDeclaredField("mCursorDrawableRes");
      fCursorDrawableRes.setAccessible(true);
      int mCursorDrawableRes = fCursorDrawableRes.getInt(editText);
      Field fEditor = TextView.class.getDeclaredField("mEditor");
      fEditor.setAccessible(true);
      Object editor = fEditor.get(editText);
      Class<?> clazz = editor.getClass();
      Field fCursorDrawable = clazz.getDeclaredField("mCursorDrawable");
      fCursorDrawable.setAccessible(true);
      Drawable[] drawables = new Drawable[2];
      drawables[0] = ContextCompat.getDrawable(editText.getContext(), mCursorDrawableRes);
      drawables[1] = ContextCompat.getDrawable(editText.getContext(), mCursorDrawableRes);
      drawables[0].setColorFilter(color, PorterDuff.Mode.SRC_IN);
      drawables[1].setColorFilter(color, PorterDuff.Mode.SRC_IN);
      fCursorDrawable.set(editor, drawables);
    } catch (NoSuchFieldException e1) {
      Log.d("MDTintHelper", "Device issue with cursor tinting: " + e1.getMessage());
      e1.printStackTrace();
    } catch (Exception e2) {
      e2.printStackTrace();
    }
  }
}
